package com.stars.easyms.redis.interceptor;

import com.stars.easyms.redis.annotion.RedisExists;
import com.stars.easyms.redis.exception.RedisInterceptorException;
import com.stars.easyms.redis.exception.RedisRuntimeException;
import com.stars.easyms.base.util.GenericTypeUtil;
import com.stars.easyms.base.util.ReflectUtil;
import org.aopalliance.intercept.MethodInvocation;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Set;

/**
 * <p>className: RedisExistsInterceptor</p>
 * <p>description: RedisExists注解拦截器</p>
 *
 * @author guoguifang
 * @version 1.2.1
 * @date 2019-03-18 14:39
 */
public class RedisExistsInterceptor extends AbstractRedisInterceptor<RedisExists> {

    @Override
    protected Object invoke(MethodInvocation methodInvocation, RedisExists redisExists) throws RedisInterceptorException {
        if (isEnabled()) {
            Method pointMethod = methodInvocation.getMethod();
            Class<?> returnType = pointMethod.getReturnType();
            Set<String> hashKeySet = getRedisHashKey(methodInvocation);
            int hashKeySetSize = hashKeySet.size();
            if (hashKeySetSize <= 1) {
                if (!Boolean.class.isAssignableFrom(returnType)
                        && !boolean.class.isAssignableFrom(returnType)) {
                    throw new RedisRuntimeException("Method '{}' when have just only one redis field or not, returnType should be Boolean or boolean!",
                            ReflectUtil.getMethodFullName(pointMethod));
                }
            } else {
                Type genericReturnType = pointMethod.getGenericReturnType();
                if (!Map.class.isAssignableFrom(returnType)
                        || !String.class.isAssignableFrom(GenericTypeUtil.getGenericClass(genericReturnType, 0))
                        || !Boolean.class.isAssignableFrom(GenericTypeUtil.getGenericClass(genericReturnType, 1))) {
                    throw new RedisRuntimeException("Method '{}' when have more than one redis field, returnType should be Map<String, Boolean>!",
                            ReflectUtil.getMethodFullName(pointMethod));
                }
            }
            String redisKey = getRedisKey(methodInvocation, redisExists.group());
            if (hashKeySetSize == 0) {
                return easyMsRedisTemplate.hasKey(redisKey);
            } else if (hashKeySetSize == 1) {
                return easyMsRedisTemplate.hashHasKey(redisKey, (String) hashKeySet.toArray()[0]);
            } else {
                return easyMsRedisTemplate.hashHasKey(redisKey, hashKeySet);
            }
        }
        return proceed(methodInvocation);
    }

}